package com.polaris.live.ui.live.proxy

import android.view.TextureView
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.viewModelScope
import com.faceunity.wrapper.faceunity
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.utils.zego.PublishingStreamProxy
import com.polaris.live.utils.zego.beauty.FaceManager
import com.polaris.live.utils.zego.beauty.FaceUnity
import com.polaris.live.utils.zego.beauty.OnFaceStateChangeListener
import im.zego.zegoexpress.ZegoExpressEngine
import im.zego.zegoexpress.callback.IZegoCustomVideoProcessHandler
import im.zego.zegoexpress.constants.ZegoPublishChannel
import im.zego.zegoexpress.constants.ZegoVideoConfigPreset
import im.zego.zegoexpress.constants.ZegoVideoMirrorMode
import im.zego.zegoexpress.constants.ZegoViewMode
import im.zego.zegoexpress.entity.ZegoCanvas
import im.zego.zegoexpress.entity.ZegoVideoConfig
import kotlinx.coroutines.launch

/**
 * LiveEngineProxy
 *
 * @author Created by lucas on 2023/11/10 15:54
 */
class LiveEngineProxy(
    private val owner: LifecycleOwner,
    private val engine: ZegoExpressEngine,
    private val viewModel: BaseViewModel,
    private val onFaceStateChangeListener: OnFaceStateChangeListener?,
) {

    private val faceUnity: FaceUnity

    private var lastPublishSteamId: String? = null

    private var lastFaceTrackingTime: Long? = null
    private var lastFaceNumber: Int? = null

    init {
        faceUnity = FaceManager.createFaceUnity().apply {
            observe(owner)
        }

        owner.lifecycle.addObserver(object : LifecycleEventObserver {
            override fun onStateChanged(source: LifecycleOwner, event: Lifecycle.Event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    faceUnity.onReleaseUnity()

                    engine.setCustomVideoProcessHandler(null)
                }
            }
        })
    }

    /**
     * 仅浏览
     */
    fun startPreview(view: TextureView) {
        // 设置本地预览视图并启动预览，视图模式采用 SDK
        val previewCanvas = ZegoCanvas(view).apply {
            viewMode = ZegoViewMode.ASPECT_FILL
        }

        //开启美颜
        registerBeauty()

        engine.enableCamera(true)
        engine.muteMicrophone(false)

        //默认设置为540p
        engine.videoConfig = ZegoVideoConfig(ZegoVideoConfigPreset.PRESET_540P)

        engine.startPreview(previewCanvas)
        engine.setVideoMirrorMode(ZegoVideoMirrorMode.ONLY_PREVIEW_MIRROR)

    }

    /**
     * 开始推流
     */
    fun startPublish(streamId: String, view: TextureView) {
        startPreview(view)

        invokePublish(streamId)
    }

    private fun invokePublish(streamId: String) {
        PublishingStreamProxy.start(hashCode(), streamId) {
            if (it) {
                engine.startPublishingStream(streamId)
                lastPublishSteamId = streamId
                lastFaceNumber = null
            }
        }
    }

    /**
     * 注册美颜配置
     */
    private fun registerBeauty() {
        engine.setCustomVideoProcessHandler(object : IZegoCustomVideoProcessHandler() {

            override fun onCapturedUnprocessedTextureData(
                textureID: Int,
                width: Int,
                height: Int,
                referenceTimeMillisecond: Long,
                channel: ZegoPublishChannel?,
            ) {
                val texId = faceUnity.renderToTexture(textureID, width, height)
                engine.sendCustomVideoProcessedTextureData(
                    texId,
                    width,
                    height,
                    referenceTimeMillisecond
                )

                val lastFaceTrackingTime = lastFaceTrackingTime
                val currentTime = System.currentTimeMillis()
                if (lastFaceTrackingTime == null || currentTime - lastFaceTrackingTime > 1000) {
                    onChangeFace(faceunity.fuIsTracking())
                    this@LiveEngineProxy.lastFaceTrackingTime = currentTime
                }
            }

        })
    }

    private fun onChangeFace(tracking: Int) {
        if (onFaceStateChangeListener == null) return

        if (tracking != lastFaceNumber) {
            val valid = tracking > 0
            viewModel.viewModelScope.launch {
                onFaceStateChangeListener.onFaceStateChange(valid)
            }
        }

        lastFaceNumber = tracking
    }

    /**
     * 切换view浏览
     */
    fun switchPreview(view: TextureView) {
        val previewCanvas = ZegoCanvas(view).apply {
            viewMode = ZegoViewMode.ASPECT_FILL
        }
        engine.startPreview(previewCanvas)
    }

    /**
     * 恢复推流
     */
    fun resumePublish(streamId: String) {
        invokePublish(streamId)
    }

    /**
     * 暂停推流
     */
    fun pausePublish() {
        PublishingStreamProxy.checkState(
            hashCode(),
            lastPublishSteamId
        ) {
            if (it) {
                engine.stopPublishingStream()
            }
        }
        lastPublishSteamId = null
    }

    /**
     * 停止推流
     */
    fun stopPublish() {
        engine.setCustomVideoProcessHandler(null)
        PublishingStreamProxy.checkState(
            hashCode(),
            lastPublishSteamId
        ) {
            if (it) {
                initiativeStopPublish()
            }
        }

        lastPublishSteamId = null
    }

    /**
     * 停止推流流程
     */
    fun initiativeStopPublish() {
        engine.enableCamera(false)
        engine.muteMicrophone(true)
        engine.stopPublishingStream()
        engine.stopPreview()
    }
}